Skip to content

ci: make path-filtered required gates always report (unblock stuck PRs)#216

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/ci-required-check-skip-shim
Jun 13, 2026
Merged

ci: make path-filtered required gates always report (unblock stuck PRs)#216
hyperpolymath merged 1 commit into
mainfrom
claude/ci-required-check-skip-shim

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

What this fixes

PRs #213 (dependabot flake.lock) and #215 (scripts-only) are stuck at mergeable_state: blocked despite every check green (and #213 approved). Root cause: seven gates are workflow-level path-filtered (on.*.paths). When a PR touches none of a gate's paths the workflow never runs, so its required status check stays "Expected" forever → permanent block.

The asymmetry this exploits: a path-filtered workflow that never runs blocks; a job skipped via if: reports SUCCESS to required checks. This converts the former into the latter.

Change (uniform across all 7)

abi-drift, backend-assurance, e2e, lsp-dap-bsp, proofs, truthfulness, zig-test:

  1. Drop the on.*.paths filter → the workflow always runs, so the required check is always created.
  2. Add a lightweight changes job that recomputes the gate's original path set via git diff origin/<base>...HEAD (the same pattern abi-drift/zig-test already use internally).
  3. Gate every heavy job with needs: changes + if: needs.changes.outputs.run == 'true'. Nothing relevant changed → heavy job skipped → passes → PR unblocked and no wasted CI.

No branch-protection change needed — job/check names are unchanged. workflow_dispatch added to all 7 for manual full runs.

Safety

  • Fail-safe toward running: the detector defaults run=true and only sets false when a successful diff shows no relevant path changed (any fetch/diff error or unknown base ⇒ run). The dangerous direction — skipping a gate that should run — can't happen on detection failure.
  • Each regex mirrors the gate's original paths:, so a relevant change runs it exactly as before (verified: 77/77 unit checks — abi/→proofs+abi-drift, ffi/→zig+truthfulness+abi-drift, SafetyLemmas.idr→backend-assurance+proofs, etc.; chore(deps): bump nixpkgs from 8c3cede to 8c91a71 #213/feat(scripts): extend §1.5 verb-canary coverage (Phase E) #215 → all skip).

Validation

actionlint -shellcheck=  (all 7)        → EXIT 0   (structure/expressions/needs-graph valid)
actionlint (all 7)                      → only PRE-EXISTING shellcheck infos in original run-scripts (untouched)
detection regexes (77 checks)           → 77/77 correct
gated heavy jobs                        → 15/15 (abi-drift 1, backend-assurance 1, e2e 5, lsp-dap-bsp 4, proofs 2, truthfulness 1, zig-test 1)
leftover path filters                   → 0

Self-validating: editing a workflow file no longer self-triggers its heavy gate (kept out of each regex), so this PR's own checks exercise the skip path — the gates should report skipped/success here, demonstrating the unblock live.

Draft — why

I can't runtime-test the run=true branch (it needs the GH runners), and this changes how required gates fire, so it wants your eyes before merge. Mark ready / squash-merge when you're satisfied. After it lands, re-check #213/#215 — they should flip from blocked to mergeable.

Out of scope (flagged, not fixed): the pre-existing shellcheck infos in abi-drift/zig-test original scripts, and the Hypatia baseline backlog (stale GEMINI.md, unpinned governance.yml action, missing_timeout_minutes on several workflows) — these are non-blocking and belong in a separate hygiene pass.

https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa


Generated by Claude Code

Seven gates were workflow-level path-filtered (on.*.paths). When a PR
touched none of a gate's paths the workflow never ran, so its REQUIRED
status check stayed "Expected" forever and the PR sat at
mergeable_state=blocked — even with every other check green and the PR
approved (e.g. #213 flake.lock bump, #215 scripts-only). The asymmetry
this fixes: a path-filtered workflow that never runs BLOCKS, whereas a
job skipped via `if:` reports SUCCESS to required checks.

For each of abi-drift, backend-assurance, e2e, lsp-dap-bsp, proofs,
truthfulness, zig-test:
  * drop the workflow-level `on.*.paths` filter (always run, so the
    required check is always created),
  * add a lightweight `changes` job that recomputes the gate's original
    path set via `git diff origin/<base>...HEAD` (the same pattern
    abi-drift/zig-test already used internally for per-cartridge scoping),
  * gate every heavy job with `needs: changes` +
    `if: needs.changes.outputs.run == 'true'`. When nothing relevant
    changed the heavy job is skipped (a passing required check), so
    unrelated PRs are no longer blocked AND don't pay for the heavy work.

Fail-safe: the detector defaults to run=true and only skips when a
SUCCESSFUL diff shows no relevant path changed (any fetch/diff error or
unknown base => run). The dangerous direction — skipping a gate that
should run — cannot happen on detection failure. Each regex mirrors the
gate's original `paths:`, so a relevant change runs it exactly as before.

No branch-protection change needed: job/check names are unchanged.
workflow_dispatch added to all 7 for manual full runs.

Validated locally: actionlint clean on all 7 (only pre-existing
shellcheck infos remain, untouched); detection regexes unit-tested
against representative change-sets (77/77, incl. #213/#215 -> skip and
abi/ffi/src changes -> run).

Note: editing a workflow file no longer self-triggers its heavy gate
(kept out of each regex), so workflow-only PRs like THIS one exercise the
skip path and stay green.

https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 272 issues detected

Severity Count
🔴 Critical 15
🟠 High 138
🟡 Medium 119

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Stale AI session file -- delete",
    "type": "stale",
    "file": "GEMINI.md",
    "action": "delete",
    "rule_module": "root_hygiene",
    "severity": "medium"
  },
  {
    "reason": "Issue in abi-drift.yml",
    "type": "missing_timeout_minutes",
    "file": "abi-drift.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "missing_timeout_minutes",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in container-publish.yml",
    "type": "missing_timeout_minutes",
    "file": "container-publish.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath marked this pull request as ready for review June 13, 2026 12:01
@hyperpolymath hyperpolymath merged commit ece30ad into main Jun 13, 2026
48 checks passed
@hyperpolymath hyperpolymath deleted the claude/ci-required-check-skip-shim branch June 13, 2026 12:01
hyperpolymath added a commit that referenced this pull request Jun 13, 2026
…219)

Documentation-only follow-up to #216 — captures the required-gate
"skip-shim" as a durable convention so it can't be silently regressed,
and records the work in machine-readable state. **No workflow or code
changes.**

## What's added
- **`docs/AI-CONVENTIONS.adoc`** — new "CI / Required Status Checks"
section (the do/don't rule). Also fixes a **stale** Banned-Languages
row: `TypeScript → AffineScript` (not ReScript — retired as the
destination 2026-04-30, per CLAUDE.md).
- **`.claude/CLAUDE.md`** — matching "CI / Required Status Checks"
section for AI agents.
- **`docs/wikis/CI-and-Required-Checks.adoc`** — new developer wiki
page: the problem (path-filtered required check → permanent "Expected" →
blocked PR), the fix, a copy-paste workflow template, a do/don't table,
and the green-but-blocked diagnostic. Linked from `Home.adoc`.
- **`.machine_readable/6a2/STATE.a2ml`** — 2026-06-13 session entry
(#216 + merged #213/#215 + follow-ups #218/#46/#47/#48); `last-updated`
bumped.
- **`.machine_readable/6a2/PLAYBOOK.a2ml`** — `[ci-required-gates]`
runbook section.
- **`CONTRIBUTING.md`** — brief pointer note.

Both a2ml files verified to still parse as TOML. Draft for your review.

https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa

---
_Generated by [Claude
Code](https://claude.ai/code/session_019tMcRS1Dm1nWjjYP4WvbJa)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants